home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / utils / file / logiso.000 / logiso / RCS / namei.c,v < prev   
Encoding:
Text File  |  1995-03-24  |  7.1 KB  |  331 lines

  1. head    1.4;
  2. access;
  3. symbols
  4.     VER_0_3:1.4
  5.     VER_0_2:1.3;
  6. locks; strict;
  7. comment    @ * @;
  8.  
  9.  
  10. 1.4
  11. date    95.03.24.11.44.17;    author coulter;    state Exp;
  12. branches;
  13. next    1.3;
  14.  
  15. 1.3
  16. date    95.03.10.02.43.06;    author coulter;    state Exp;
  17. branches;
  18. next    1.2;
  19.  
  20. 1.2
  21. date    95.02.13.20.56.00;    author coulter;    state Exp;
  22. branches;
  23. next    1.1;
  24.  
  25. 1.1
  26. date    95.02.11.15.47.56;    author coulter;    state Exp;
  27. branches;
  28. next    ;
  29.  
  30.  
  31. desc
  32. @namei.c - adding logging ioctl.
  33. @
  34.  
  35.  
  36. 1.4
  37. log
  38. @Checkin version for 0.3 distribution.
  39. @
  40. text
  41. @/*
  42.  *  linux/fs/isofs/namei.c
  43.  * 
  44.  *  Copyright 1995 Michael Coulter for access logging.
  45.  *
  46.  *  (C) 1992  Eric Youngdale Modified for ISO9660 filesystem.
  47.  *
  48.  *  (C) 1991  Linus Torvalds - minix filesystem
  49.  */
  50.  
  51. #include <linux/sched.h>
  52. #include <linux/iso_fs.h>
  53. #include <linux/kernel.h>
  54. #include <linux/string.h>
  55. #include <linux/stat.h>
  56. #include <linux/fcntl.h>
  57. #include <asm/segment.h>
  58. #include <linux/malloc.h>
  59.  
  60. #include <linux/errno.h>
  61.  
  62. /*
  63.  * ok, we cannot use strncmp, as the name is not in our data space.
  64.  * Thus we'll have to use isofs_match. No big problem. Match also makes
  65.  * some sanity tests.
  66.  *
  67.  * NOTE! unlike strncmp, isofs_match returns 1 for success, 0 for failure.
  68.  */
  69. static int isofs_match(int len,const char * name, char * compare, int dlen)
  70. {
  71.     if (!compare)
  72.         return 0;
  73.  
  74.     /* check special "." and ".." files */
  75.     if (dlen == 1) {
  76.         /* "." */
  77.         if (compare[0] == 0) {
  78.             if (!len)
  79.                 return 1;
  80.             compare = ".";
  81.         } else if (compare[0] == 1) {
  82.             compare = "..";
  83.             dlen = 2;
  84.         }
  85.     }
  86. #if 0
  87.     if (len <= 2) printk("Match: %d %d %s %d %d \n",len,dlen,compare,de->name[0], dlen);
  88. #endif
  89.     
  90.     if (dlen != len)
  91.         return 0;
  92.     return !memcmp(name, compare, len);
  93. }
  94.  
  95. /*
  96.  *    isofs_find_entry()
  97.  *
  98.  * finds an entry in the specified directory with the wanted name. It
  99.  * returns the cache buffer in which the entry was found, and the entry
  100.  * itself (as an inode number). It does NOT read the inode of the
  101.  * entry - you'll have to do that yourself if you want to.
  102.  */
  103. static struct buffer_head * isofs_find_entry(struct inode * dir,
  104.     const char * name, int namelen, unsigned long * ino, unsigned long * ino_back)
  105. {
  106.     unsigned long bufsize = ISOFS_BUFFER_SIZE(dir);
  107.     unsigned char bufbits = ISOFS_BUFFER_BITS(dir);
  108.     unsigned int block, i, f_pos, offset, inode_number;
  109.     struct buffer_head * bh;
  110.     void * cpnt = NULL;
  111.     unsigned int old_offset;
  112.     unsigned int backlink;
  113.     int dlen, rrflag, match;
  114.     char * dpnt;
  115.     struct iso_directory_record * de;
  116.     char c;
  117.  
  118.     *ino = 0;
  119.     if (!dir) return NULL;
  120.     
  121.     if (!(block = dir->u.isofs_i.i_first_extent)) return NULL;
  122.   
  123.     f_pos = 0;
  124.  
  125.     offset = f_pos & (bufsize - 1);
  126.     block = isofs_bmap(dir,f_pos >> bufbits);
  127.  
  128.     if (!block || !(bh = bread(dir->i_dev,block,bufsize))) return NULL;
  129.   
  130.     while (f_pos < dir->i_size) {
  131.         de = (struct iso_directory_record *) (bh->b_data + offset);
  132.         backlink = dir->i_ino;
  133.         inode_number = (block << bufbits) + (offset & (bufsize - 1));
  134.  
  135.         /* If byte is zero, this is the end of file, or time to move to
  136.            the next sector. Usually 2048 byte boundaries. */
  137.         
  138.         if (*((unsigned char *) de) == 0) {
  139.             brelse(bh);
  140.             offset = 0;
  141.             f_pos = ((f_pos & ~(ISOFS_BLOCK_SIZE - 1))
  142.                  + ISOFS_BLOCK_SIZE);
  143.             block = isofs_bmap(dir,f_pos>>bufbits);
  144.             if (!block || !(bh = bread(dir->i_dev,block,bufsize)))
  145.                 return 0;
  146.             continue; /* Will kick out if past end of directory */
  147.         }
  148.  
  149.         old_offset = offset;
  150.         offset += *((unsigned char *) de);
  151.         f_pos += *((unsigned char *) de);
  152.  
  153.         /* Handle case where the directory entry spans two blocks.
  154.            Usually 1024 byte boundaries */
  155.         if (offset >= bufsize) {
  156.                 unsigned int frag1;
  157.             frag1 = bufsize - old_offset;
  158.             cpnt = kmalloc(*((unsigned char *) de),GFP_KERNEL);
  159.             memcpy(cpnt, bh->b_data + old_offset, frag1);
  160.  
  161.             de = (struct iso_directory_record *) cpnt;
  162.             brelse(bh);
  163.             offset = f_pos & (bufsize - 1);
  164.             block = isofs_bmap(dir,f_pos>>bufbits);
  165.             if (!block || !(bh = bread(dir->i_dev,block,bufsize))) {
  166.                     kfree(cpnt);
  167.                 return 0;
  168.             };
  169.             memcpy((char *)cpnt+frag1, bh->b_data, offset);
  170.         }
  171.         
  172.         /* Handle the '.' case */
  173.         
  174.         if (de->name[0]==0 && de->name_len[0]==1) {
  175.             inode_number = dir->i_ino;
  176.             backlink = 0;
  177.         }
  178.         
  179.         /* Handle the '..' case */
  180.  
  181.         if (de->name[0]==1 && de->name_len[0]==1) {
  182. #if 0
  183.             printk("Doing .. (%d %d)",
  184.                    dir->i_sb->s_firstdatazone << bufbits,
  185.                    dir->i_ino);
  186. #endif
  187.             if((dir->i_sb->u.isofs_sb.s_firstdatazone
  188.                 << bufbits) != dir->i_ino)
  189.                 inode_number = dir->u.isofs_i.i_backlink;
  190.             else
  191.                 inode_number = dir->i_ino;
  192.             backlink = 0;
  193.         }
  194.     
  195.         dlen = de->name_len[0];
  196.         dpnt = de->name;
  197.         /* Now convert the filename in the buffer to lower case */
  198.         rrflag = get_rock_ridge_filename(de, &dpnt, &dlen, dir);
  199.         if (rrflag) {
  200.           if (rrflag == -1) goto out; /* Relocated deep directory */
  201.         } else {
  202.           if(dir->i_sb->u.isofs_sb.s_mapping == 'n') {
  203.             for (i = 0; i < dlen; i++) {
  204.               c = dpnt[i];
  205.               if (c >= 'A' && c <= 'Z') c |= 0x20;  /* lower case */
  206.               if (c == ';' && i == dlen-2 && dpnt[i+1] == '1') {
  207.             dlen -= 2;
  208.             break;
  209.               }
  210.               if (c == ';') c = '.';
  211.               de->name[i] = c;
  212.             }
  213.             /* This allows us to match with and without a trailing
  214.                period.  */
  215.             if(dpnt[dlen-1] == '.' && namelen == dlen-1)
  216.               dlen--;
  217.           }
  218.         }
  219.         match = isofs_match(namelen,name,dpnt,dlen);
  220.         if (cpnt) {
  221.             kfree(cpnt);
  222.             cpnt = NULL;
  223.         }
  224.  
  225.         if(rrflag) kfree(dpnt);
  226.         if (match) {
  227.             if(inode_number == -1) {
  228.                 /* Should only happen for the '..' entry */
  229.                 inode_number = 
  230.                     isofs_lookup_grandparent(dir,
  231.                        find_rock_ridge_relocation(de,dir));
  232.                 if(inode_number == -1){
  233.                     /* Should never happen */
  234.                     printk("Backlink not properly set.\n");
  235.                     goto out;
  236.                 }
  237.             }
  238.             *ino = inode_number;
  239.             *ino_back = backlink;
  240.             return bh;
  241.         }
  242.     }
  243.  out:
  244.     if (cpnt)
  245.         kfree(cpnt);
  246.     brelse(bh);
  247.     return NULL;
  248. }
  249.  
  250. int isofs_lookup(struct inode * dir,const char * name, int len,
  251.     struct inode ** result)
  252. {
  253.     unsigned long ino, ino_back;
  254.     struct buffer_head * bh;
  255.  
  256. #ifdef DEBUG
  257.     printk("lookup: %x %d\n",dir->i_ino, len);
  258. #endif
  259.     iso_log_add(dir->i_ino, dir->i_dev, ISO_LOG_OP_isofs_lookup);
  260.     *result = NULL;
  261.     if (!dir)
  262.         return -ENOENT;
  263.  
  264.     if (!S_ISDIR(dir->i_mode)) {
  265.         iput(dir);
  266.         return -ENOENT;
  267.     }
  268.  
  269.     ino = 0;
  270.  
  271.     if (dcache_lookup(dir, name, len, &ino)) ino_back = dir->i_ino;
  272.  
  273.     if (!ino) {
  274.       if (!(bh = isofs_find_entry(dir,name,len, &ino, &ino_back))) {
  275.         iput(dir);
  276.         return -ENOENT;
  277.       }
  278.       if (ino_back == dir->i_ino)
  279.         dcache_add(dir, name, len, ino);
  280.       brelse(bh);
  281.     };
  282.  
  283.     if (!(*result = iget(dir->i_sb,ino))) {
  284.         iput(dir);
  285.         return -EACCES;
  286.     }
  287.  
  288.     /* We need this backlink for the ".." entry unless the name that we
  289.        are looking up traversed a mount point (in which case the inode
  290.        may not even be on an iso9660 filesystem, and writing to
  291.        u.isofs_i would only cause memory corruption).
  292.     */
  293.     
  294.     if (ino_back && !(*result)->i_pipe && (*result)->i_sb == dir->i_sb) {
  295.       (*result)->u.isofs_i.i_backlink = ino_back; 
  296.     }
  297.     
  298.     iput(dir);
  299.     return 0;
  300. }
  301. @
  302.  
  303.  
  304. 1.3
  305. log
  306. @Checkin files modified to make version 0.2
  307. @
  308. text
  309. @d3 2
  310. @
  311.  
  312.  
  313. 1.2
  314. log
  315. @Checkin working version.  Try to make it dynamic now.
  316. @
  317. text
  318. @d217 1
  319. a217 1
  320.     iso_log_add(dir->i_ino, ISO_LOG_OP_isofs_lookup);
  321. @
  322.  
  323.  
  324. 1.1
  325. log
  326. @Initial revision
  327. @
  328. text
  329. @d217 1
  330. @
  331.